package orm

import (
	"errors"
	"fmt"
	"log"
	"time"

	"gopkg.in/natefinch/lumberjack.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"

	"gitee.com/danqingzhao/go-dango/pkg/third/orm/driver/opengauss"
)

func InitGormDB(c *DBConf, l *lumberjack.Logger) (*gorm.DB, error) {
	if c == nil {
		return nil, errors.New("gorm config is nil")
	}
	var gc gorm.Config
	gc.SkipDefaultTransaction = false
	gc.FullSaveAssociations = false
	gc.TranslateError = true
	if l != nil {
		dbLog := log.New(l, " ", log.LstdFlags)
		gc.Logger = logger.New(dbLog, logger.Config{
			SlowThreshold:             time.Second,
			Colorful:                  false,
			IgnoreRecordNotFoundError: false,
			ParameterizedQueries:      false,
			LogLevel:                  logger.Info,
		})
	}
	var (
		db      *gorm.DB
		openErr error
	)
	switch c.DbType {
	case "mysql":
		dsn := fmt.Sprintf(
			"%s:%s@tcp(%s:%d)/%s?parseTime=True&loc=Local",
			c.DbUser, c.DbPassword, c.DbHost, c.DbPort, c.DbName,
		)
		db, openErr = gorm.Open(mysql.Open(dsn), &gc)
	case "opengauss":
		dsn := fmt.Sprintf(
			"host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Asia/Shanghai",
			c.DbHost, c.DbUser, c.DbPassword, c.DbName, c.DbPort,
		)
		db, openErr = gorm.Open(opengauss.Open(dsn), &gc)
	default:
		return nil, gorm.ErrUnsupportedDriver
	}
	if openErr != nil {
		return nil, gorm.ErrInvalidDB
	}
	sqlDB, err := db.DB()
	if err != nil {
		return nil, gorm.ErrInvalidDB
	}
	if c.MaxIdleConns != 0 {
		sqlDB.SetMaxIdleConns(int(c.MaxIdleConns))
	}
	if c.MaxOpenConns != 0 {
		sqlDB.SetMaxOpenConns(int(c.MaxOpenConns))
	}
	if c.ConnMaxLifetime != 0 {
		sqlDB.SetConnMaxLifetime(time.Duration(c.ConnMaxLifetime) * time.Second)
	}
	return db, nil
}

func CloseGormDB(db *gorm.DB) error {
	if db == nil {
		return gorm.ErrInvalidDB
	}
	sqlDB, err := db.DB()
	if err != nil {
		return gorm.ErrInvalidDB
	}
	return sqlDB.Close()
}
